import axios from 'axios';
import * as vscode from 'vscode';
import { AgentViewController } from './AgentViewController';

export class AgentViewProvider implements vscode.WebviewViewProvider {
	public static readonly viewType = 'agent.agentView';
	view?: vscode.WebviewView;
	controller: AgentViewController;
	constructor(
		private readonly context: vscode.ExtensionContext,
		private readonly outputChannel: vscode.OutputChannel,
	) { 
		this.controller = new AgentViewController(context, outputChannel, this);
	}

	async resolveWebviewView(webviewView: vscode.WebviewView, _context: vscode.WebviewViewResolveContext, _token: vscode.CancellationToken) {
		this.view = webviewView;

		webviewView.webview.options = {
			enableScripts: true,
			localResourceRoots: [
				this.context.extensionUri
			]
		};
		// 构建html
		webviewView.webview.html =
			this.context.extensionMode === vscode.ExtensionMode.Development
				? await this.getHMRHtmlContent(webviewView.webview)
				: this.getHtmlForWebview(webviewView.webview);

		// 监听消息
		webviewView.webview.onDidReceiveMessage((message) => {
			this.handleReceivedMessage(message);
		});
	}

	private handleReceivedMessage(message: any) {
		this.controller.handleReceivedWebViewMessage(message);
	}


	private async getHMRHtmlContent(webview: vscode.Webview): Promise<string> {
		const localPort = 9967;
		const localServerUrl = `localhost:${localPort}`;

		try {
			await axios.get(`http://${localServerUrl}`);
		} catch (error) {
			console.log(error);
			vscode.window.showErrorMessage(
				"AI Code Agent: 本地服务未启动,HMR无法工作。请运行'npm run dev:webview'命令启动本地服务。",
			);

			return this.getHtmlForWebview(webview);
		}

		const nonce = getNonce();
		const stylesUri = getUri(webview, this.context.extensionUri, ["ui", "build", "assets", "index.css"]);
		const codiconsUri = getUri(webview, this.context.extensionUri, [
			"ui",
			"node_modules",
			"@vscode",
			"codicons",
			"dist",
			"codicon.css",
		]);

		const scriptEntrypoint = "src/main.tsx";
		const scriptUri = `http://${localServerUrl}/${scriptEntrypoint}`;

		const reactRefresh = /*html*/ `
			<script nonce="${nonce}" type="module">
				import RefreshRuntime from "http://${localServerUrl}/@react-refresh"
				RefreshRuntime.injectIntoGlobalHook(window)
				window.$RefreshReg$ = () => {}
				window.$RefreshSig$ = () => (type) => type
				window.__vite_plugin_react_preamble_installed__ = true
			</script>
		`;

		const csp = [
			"default-src 'none'",
			`font-src ${webview.cspSource}`,
			`style-src ${webview.cspSource} 'unsafe-inline' https://* http://${localServerUrl} http://0.0.0.0:${localPort}`,
			`img-src ${webview.cspSource} https: data:`,
			`script-src 'unsafe-eval' https://* http://${localServerUrl} http://0.0.0.0:${localPort} 'nonce-${nonce}'`,
			`connect-src https://* ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`,
		];

		return /*html*/ `
			<!DOCTYPE html>
			<html lang="en">
				<head>
					<meta charset="utf-8">
					<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
					<meta http-equiv="Content-Security-Policy" content="${csp.join("; ")}">
					<link rel="stylesheet" type="text/css" href="${stylesUri}">
					<link rel="stylesheet" href="${codiconsUri}">
					<title>AI Code Agent</title>
				</head>
				<body>
					<div id="root"></div>
					${reactRefresh}
					<script type="module" src="${scriptUri}"></script>
				</body>
			</html>
		`;
	}

	private getHtmlForWebview(webview: vscode.Webview) {
		// 加载脚本文件
		const scriptUri = webview.asWebviewUri(vscode.Uri.joinPath(this.context.extensionUri, 'ui', 'build', 'assets', 'index.js'));

		// 获取样式文件
		const styleResetUri = webview.asWebviewUri(vscode.Uri.joinPath(this.context.extensionUri, 'ui', 'build', 'assets', 'index.css'));

		// 生成随机字符串，防止xss攻击
		const nonce = getNonce();

		return `<!DOCTYPE html>
			<html lang="en">
			<head>
				<meta charset="UTF-8">
				<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
				<meta name="theme-color" content="#000000">
				<meta http-equiv="Content-Security-Policy" content="default-src 'none'; connect-src https://*.posthog.com https://*.firebaseauth.com https://*.firebaseio.com https://*.googleapis.com https://*.firebase.com; font-src ${webview.cspSource}; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} https: data:; script-src 'nonce-${nonce}' 'unsafe-eval';">
				<link href="${styleResetUri}" rel="stylesheet">
				<title>AI Code Agent</title>
			</head>
			<body>
				<noscript>You need to enable JavaScript to run this app.</noscript>
				<div id="root"></div>
				<script nonce="${nonce}" type="module" src="${scriptUri}"></script>
			</body>
			</html>`;
	}
}
// 生成随机字符串
function getNonce() {
	let text = '';
	const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
	for (let i = 0; i < 32; i++) {
		text += possible.charAt(Math.floor(Math.random() * possible.length));
	}
	return text;
}

function getUri(webview: vscode.Webview, extensionUri: vscode.Uri, pathList: string[]) {
	return webview.asWebviewUri(vscode.Uri.joinPath(extensionUri, ...pathList));
}